package de.backtomedieval.game;

import java.util.ArrayList;
import java.util.Random;

import de.backtomedieval.buildings.AbstractBuilding;
import de.backtomedieval.buildings.Academy;
import de.backtomedieval.error.BuildingAlreadyExitsException;
import de.backtomedieval.error.NotEnoughWaresException;
import de.backtomedieval.main.Game;
import de.backtomedieval.research.AbstractResearch;
import de.backtomedieval.research.Technology;
import de.backtomedieval.units.*;

public class KI {
	
	private Player player;
	private City city;
	private AbstractBuilding nextToBuild = null;
	private UnitOrder nextInBarrack = null;
	private int[] updateWares;
	private int waitingBarrack = 0;
	private static final int[] reactionTimes = {20,16,12,8,4,0};
	private int reaction = 0;
	private Random rnd = new Random();
	private int power = 0;
	
	public KI(Player player, int power) {
		this.player =player;
		this.city = player.getCurrentCity();
		updateWares = city.getUpdateWares().clone();
		this.power=power;
	}
	
	public void executeKI() {
		if (reaction==0) {
			Academy a = city.getAcademy();
			if (a!=null && a.isBuilded() && a.getToResearch()==null) {
				ArrayList<AbstractResearch> researches = player.getTechnology().getResearch();
				if (researches.size()!=0) {
					int research = rnd.nextInt(researches.size());
					a.setToResearch(researches.get(research));
				}
				
			}
			if (nextInBarrack!=null) {
				waitingBarrack++;
				if (city.hasCityEnoughWaresToAffordUnits(nextInBarrack)) {
						try {
							city.buildUnits(nextInBarrack);
							nextInBarrack=null;
							waitingBarrack = 0;
						} catch (NotEnoughWaresException e) {
						}
	
				}
			}
			
			if (waitingBarrack<10) {
				if (nextToBuild!=null) {
					if (city.hasCityEnoughWaresToAffordBuilding(nextToBuild)) {
						try {
							city.buildOrUpgradeBuilding(nextToBuild);
							updateUpdateWares(nextToBuild);
							nextToBuild=null;
						} catch (BuildingAlreadyExitsException e) {
							
						} catch (NotEnoughWaresException e) {
						}
					}
				}
			}
			reaction=KI.reactionTimes[power];
		} else {
			reaction--;
		}
		
		
		if (nextToBuild==null) {
			int needed = neededWare();
			if (needed==0) {
				if(city.getFishing_hut().getLevel()>city.getFarm().getLevel()) {
					nextToBuild = city.getFarm();
				} else {
					nextToBuild = city.getFishing_hut();
				}
			} else if(needed==1) {
				nextToBuild=city.getResidential_area();
			} else if(needed==2) {
				nextToBuild=city.getLumberjack();
			} else if(needed==3) {
				nextToBuild=city.getQuarry();
			} else if(needed==4) {
				nextToBuild=city.getOre_mine();
			}
			
			if (needed!=0 && needed!=1) {
				boolean depotNeeded=false;
				
				for (int i=0; i<5; i++) {
					if (city.getWares(i)==city.getMaxDepotSpace(i)+city.getDepot().getBuildCountdown()) {
						depotNeeded=true;
						break;
					}
				}
				
				if (city.getResidential_area().getLevel()>(city.getAcademy().getLevel()*4+2) && (city.getLumberjack().getLevel()>3)) {
					nextToBuild=city.getAcademy();
				} else if (city.getOre_mine().getLevel()>(city.getBarrack().getLevel()*2)) {
					nextToBuild=city.getBarrack();
				} else if (city.getBarrack().getLevel()>(city.getManufacture().getLevel()*3+3)) {
					nextToBuild=city.getManufacture();
				} else if (depotNeeded) {
					nextToBuild=city.getDepot();
				} else if (nextToBuild.getLevel()>(city.getTimber_yard().getLevel()*2+2)) {
					nextToBuild=city.getTimber_yard();
				} else if (city.hasCityEnoughWaresToAffordBuilding(city.getDefence_wall())) {
					nextToBuild=city.getDefence_wall();
				}
			}
		}
		
		if (nextInBarrack==null && city.getBarrack().isBuilded() && city.getBarrack().getUnitsToBuild().size()<5) {
			AbstractUnit unit;
			
			int id = rnd.nextInt(7);
			if (id==0) {
				unit=new Archer(this.player.getTechnology());
			} else if (id==1) {
				unit=new ShortSwordsman(this.player.getTechnology());
			} else if (id==2) {
				unit=new LongSwordsman(this.player.getTechnology());
			} else if (id==3) {
				unit=new TwoHandedSwordman(this.player.getTechnology());
			} else if (id==4) {
				unit=new Spearman(this.player.getTechnology());
			} else if (id==5) {
				unit=new Halberdier(this.player.getTechnology());
			} else if (id==6) {
				unit=new Hoplit(this.player.getTechnology());
			} else {
				unit=new Archer(this.player.getTechnology());
			}
			nextInBarrack=new UnitOrder(unit,rnd.nextInt(4)+1);
		}
		if (waitingBarrack>30) {
			nextInBarrack=null;
			waitingBarrack=0;
		}
	}
	
	public int neededWare() {
		int lowest = 9999;
		int[] prefs = {4,7,5,8,6};
		int index = 0;
		if (updateWares[0] < 2) {
			return 0;
		}
		if (updateWares[1] < 11 && (city.getLumberjack().getLevel()>20)) {
			return 1;
		}
		if (updateWares[1] < 5 && (city.getLumberjack().getLevel()>6)) {
			return 1;
		}
		if (updateWares[1] < 3 && (city.getLumberjack().getLevel()>3)) {
			return 1;
		}
		for (int i=2; i<updateWares.length;i++) {
			if (!((city.getLumberjack().getLevel()<4) && (i==1 || i==4))) {
				if (lowest*prefs[index]> updateWares[i]*prefs[i]) {
					lowest=updateWares[i];
					index=i;
				}
			}
		}
		return index;
	}
	
	public void updateUpdateWares(AbstractBuilding a) {
		int[] oldDiff = { 0, 0, 0, 0, 0 };
		for (int i = 0; i < oldDiff.length; i++) {
			if (a.getLevel() != 0) {
				int plus = 0;
				int minus = 0;
				if (a.getEarn() != null)
					plus = a.getEarn().getWare(a.getLevel(), i);
				if (a.getCosts() != null)
					minus = a.getCosts().getSupply(
							a.getLevel(), i);
				oldDiff[i] = plus - minus;
			}
		}
		int[] newDiff = { 0, 0, 0, 0, 0 };
		for (int i = 0; i < newDiff.length; i++) {
			int plus = 0;
			int minus = 0;
			if (a.getEarn() != null)
				plus = a.getEarn().getWare(a.getLevel() + 1, i);
			if (a.getCosts() != null)
				minus = a.getCosts().getSupply(
						a.getLevel() + 1, i);

			newDiff[i] = plus - minus;
		}
		for (int i = 0; i < newDiff.length; i++) {
			updateWares[i] = updateWares[i]
					+ (newDiff[i] - oldDiff[i]);
		}
	}
	
	

	
	
}
